﻿#region Imports
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using DataAnnotationsContrib;
using DataAnnotationsContrib.Interfaces;
using Microsoft.VisualStudio.TestTools.UnitTesting;
#endregion

namespace DataAnnotationsContrib.Tests.Framework
{
    /// <summary>
    /// Serves as a base class for all algorithm tests. Performs basic minimal test functionality
    /// by exercising an IValidationAlgorithm with the passed valid and invalid values.
    /// </summary>
    [TestClass]
    public abstract class ValidationAlgorithmTest<TAlgorithm>
        where TAlgorithm : IValidationAlgorithm
    {
        #region Infrastructure
        public TestContext TestContext { get; set; }

        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // [TestCleanup()]
        // public void MyTestCleanup() { }

        private IList<string> ValidValues { get; set; }
        private IList<string> InvalidValues { get; set; }

        protected ValidationAlgorithmTest(
            IList<string> validValues, IList<string> invalidValues)
        {
            Assert.IsNotNull(validValues, "validValues must be supplied.");
            Assert.AreNotEqual(0, validValues.Count, "validValues must not contain more 0 items.");
            Assert.IsNotNull(validValues, "invalidValues must be supplied.");
            //Assert.AreNotEqual(0, invalidValues.Count, "invalidValues must not contain more 0 items.");

            this.ValidValues = validValues;
            this.InvalidValues = invalidValues;
        }

        protected virtual IValidationAlgorithm CreateAlgorithm()
        {
            return Activator.CreateInstance<TAlgorithm>();
        }
        #endregion

        #region Tests
        public void TestAllValidValuesShouldValidateTrue()
        {
            TestHelper.Trace(this.TestContext, this.ValidValues);

            var algorithm = CreateAlgorithm();
            foreach (var value in this.ValidValues)
            {
                IList<string> messages;
                bool success = algorithm.Validate(value, out messages);
                string message = "";
                if (messages.Count > 0) message = messages[0];
                Assert.IsTrue(success, String.Format("Value '{0}' unexpectedly failed validation (first validation message='{1}').", value, message));
            }
        }
        public void TestAllInvalidValuesShouldValidateFalse()
        {
            TestHelper.Trace(this.TestContext, this.InvalidValues);

            var algorithm = CreateAlgorithm();
            foreach (var value in this.InvalidValues)
            {
                Assert.IsFalse(algorithm.Validate(value), String.Format("Value '{0}' unexpectedly passed validation.", value));
            }
        }

        public void LogAllFormatStructureInfo<TFormat>(ReadOnlyCollection<TFormat> formats, Func<TFormat, string> formatter)
        {
            TestHelper.Trace(typeof(TFormat).Name);
            var fullList = new List<string>();
            int i = 0;
            foreach (var format in formats)
            {
                i++;
                var text=formatter(format);
                TestHelper.Trace("Format {0}: {1}", i, text);
                fullList.Add(text);
            }
            TestHelper.Trace(String.Join(",", fullList.ToArray()));
        }
        #endregion
    }
}
